package CarEngine;

import com.jme.input.controls.GameControl;
import com.jme.input.controls.GameControlManager;
import com.jme.input.controls.binding.KeyboardBinding;
import com.jme.input.controls.binding.MouseButtonBinding;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.scene.Controller;
import com.jme.scene.Node;
import static CarEngine.CarController.CubeAction.*;
import static com.jme.input.KeyInput.*;
import static com.jme.input.controls.binding.MouseButtonBinding.*;
 
 
public class CarController extends Controller {
 
    enum CubeAction {LEFT, RIGHT, UP, DOWN, MUP, MDW, EXIT};
 
    private final static float ROTATESPEED = 2F;
    private final static float CONFLICTION = 0.1F;
    //for manual car
    private final static float ACCM1 = 0.2F;
    private final static float ACCM2 = 0.3F;
    private final static float ACCM3 = 0.4F;
    private final static float ACCM4 = 0.5F;
    //for auto car
    private final static float ACCAT = 0.3F; 
    private final static float MAXSPEED = 15F;
 
    private final Node node;
    private String engineMode = "";
    private final GameControlManager manager;
    private float vAngle = 0F;
    private float hAngle = 3.034F;
    private float frontspeed = 0F; //speed move front
    private float backspeed = -0.5F; //speed move back
    private int currentGear = 1;
    
    public CarController(Node node, String em) {
        this.node = node;
        this.manager = new GameControlManager();
        this.engineMode = em;
        //create all actions
        for (CubeAction action : CubeAction.values()) {
            manager.addControl(action.name());
        }
        //bind keys
        bindKey(EXIT, KEY_X);
        bindKey(UP, KEY_UP);
        bindKey(DOWN, KEY_DOWN);
        bindKey(LEFT, KEY_LEFT);
        bindKey(RIGHT, KEY_RIGHT);
        bindKey(MUP, KEY_W);
        bindKey(MDW, KEY_S);
        //bind mouse buttons
        bindMouseButton(LEFT, LEFT_BUTTON);
        bindMouseButton(RIGHT, RIGHT_BUTTON);
    }
 
 
    private void bindKey(CubeAction action, int... keys) {
        final GameControl control = manager.getControl(action.name());
        for (int key : keys) {
          control.addBinding(new KeyboardBinding(key));
        }
    }
 
    private void bindMouseButton(CubeAction action, int mouseButton) {
        final GameControl control = manager.getControl(action.name());
        control.addBinding(new MouseButtonBinding(mouseButton));
    }
 
    private float value(CubeAction action) {
        return manager.getControl(action.name()).getValue();
    }
    
    private float calculateSpeed()
    {
    	if(value(UP)>=1.0)//up is pressed
    	{
    		if(engineMode.equals("M")){
    			
    			if(frontspeed <0.5){
    				if(currentGear == 1){
    					frontspeed += ACCM1;
    				}
    			}else if(frontspeed < 1){
    				if(currentGear == 1){
    					frontspeed += ACCM1;
    				}else if(currentGear == 2){
    					frontspeed += ACCM2;
    				}

    			}else if(frontspeed <4){
    				if(currentGear == 2){
    					frontspeed += ACCM2;
    				}else if(currentGear == 3){
    					frontspeed += ACCM3;
    				}
    			}else if(frontspeed <MAXSPEED){
    				if(currentGear == 3){
    					frontspeed += ACCM3;
    				}else if(currentGear == 4){
    					frontspeed += ACCM4;
    				}
    			}else if(frontspeed >=MAXSPEED){
    				if(currentGear == 1){
    					frontspeed -=(ACCM4-ACCM1);
    				}else if(currentGear == 2){
    					frontspeed -=(ACCM4-ACCM2);
    				}else if(currentGear == 3){
    					frontspeed -=(ACCM4-ACCM3);
    				}
    			}
    		}
    		else if(engineMode.equals("A")){
    			if(frontspeed < MAXSPEED)
    			{
    				frontspeed += ACCAT;
    			}
    		}
    			
    	}
    	else if(value(DOWN)>=1.0){ //if backward
    		frontspeed = backspeed;
    	}
    	else{
    		if(frontspeed>0){
    			frontspeed-= CONFLICTION;
    		}
    		else if(frontspeed <0){
    			frontspeed = 0;
    		}
    	}
    	return frontspeed;
    }
    
    private void updateGear()
    {
    	if(value(MUP)>=1)
    	{
    		if(currentGear < 5)
    		currentGear+=1;
    	}
    	else if(value(MDW)>=1)
    	{
    		if(currentGear >1)
    		currentGear-=1;
    	}
    }
 
    @Override
    public void update(float time) {
        if (value(EXIT) > 0) {
            System.exit(0); //OK, this is just a demo...
        }
        updateGear();
        hAngle += ROTATESPEED * time * (value(LEFT) - value(RIGHT));
        float move = time * calculateSpeed();
        //vAngle += SPEED * time * (value(DOWN) - value(UP));
        //node.getLocalRotation().fromAngles(vAngle, hAngle, 0f);
        node.getLocalTranslation().addLocal(move*FastMath.sin(hAngle), 0f, move*FastMath.cos(hAngle));
        node.getLocalRotation().fromAngles(0f, hAngle, 0f);
        Vector3f nv = node.getLocalTranslation();
        System.out.println("currentGear: "+currentGear+" frontspeed: "+frontspeed);
        //System.out.println(time+"hanlge: "+hAngle+"vAngle: "+vAngle);
        //System.out.println("hangle: "+hAngle+" cos: "+FastMath.cos(hAngle)+" sin: "+FastMath.sin(hAngle));
    }
}

